package migrate

import (
	"context"
	"gitee.com/hexug/go-tools/k8s"
	"gitee.com/hexug/go-tools/logger"
	mig "gitee.com/hexug/kube-sync/worker/migrate"
	"github.com/spf13/cobra"
	"k8s.io/client-go/kubernetes"
)

var (
	ctx              = context.Background()
	sourceNamespaces []string
	targetNamespaces []string
	//workloads        []string
	sourceKubeConfig string
	targetKubeConfig string
	outPath          string
	excludes         []string
	includes         []string

	sync          bool
	skipConfigMap bool
	skipPvPvc     bool
	skipSecret    bool

	Cmd = &cobra.Command{
		Use:     "migrate",
		Short:   "克隆或者迁移 kubernetes 资源",
		Long:    "克隆或者迁移 kubernetes 资源",
		Example: "kube-sync migrate",
		Run: func(cmd *cobra.Command, args []string) {
			var srcK8sClient *kubernetes.Clientset
			var destK8sClient *kubernetes.Clientset
			clusFlage := false
			if sourceKubeConfig != "" {
				kct, _, err := k8s.GetClientSetFromKubeConfig(sourceKubeConfig)
				if err != nil {
					logger.L().Fatalw("from kubeconfig get src k8s client err", "err", err)
				}
				srcK8sClient = kct
			} else {
				kct, _, err := k8s.GetClientSet()
				if err != nil {
					logger.L().Fatalw("get src k8s client err", "err", err)
				}
				srcK8sClient = kct
			}
			if targetKubeConfig != "" {
				kct, _, err := k8s.GetClientSetFromKubeConfig(targetKubeConfig)
				if err != nil {
					logger.L().Fatalw("from kubeconfig get dest k8s client err", "err", err)
				}
				destK8sClient = kct
				logger.L().Info("不同集群下的迁移")
			} else {
				clusFlage = true
				destK8sClient = srcK8sClient
			}
			if len(sourceNamespaces) == 0 {
				logger.L().Fatal("请指定源命名空间")
			}
			if clusFlage {
				if len(targetNamespaces) == 0 {
					sync = true
					logger.L().Info("当前为同集群、同命名空间，不允许直接部署，只能将资源同步到本地文件中")
				} else {
					nsDict := make(map[string]struct{})
					for _, sns := range sourceNamespaces {
						nsDict[sns] = struct{}{}
					}
					flag := true
					for _, tns := range targetNamespaces {
						if _, ok := nsDict[tns]; ok {
							sync = true
							flag = false
							logger.L().Infof("目标命名空间 %s 在 源命名空间中存在，当前只能将源命名空间的资源同步到本地文件中", tns)
							break
						}
					}
					if flag {
						logger.L().Info("当前是在集群下的不同命名空间下做资源迁移")
					}
				}
			} else {
				if len(targetNamespaces) == 0 {
					logger.L().Debug("不同集群的迁移，未指定目标命名空间，则迁移到目标集群的对应源命名空间下")
				}
			}
			//实际工作部分
			//开始运行
			wm := mig.NewWorkloadMigrator(
				ctx,
				sourceNamespaces, targetNamespaces,
				excludes, includes,
				outPath,
				srcK8sClient, destK8sClient,
				targetKubeConfig,
				sync,
				skipConfigMap, skipPvPvc, skipSecret,
			)
			wm.Run()
		},
	}
)

func init() {
	Cmd.Flags().StringVarP(&outPath, "out", "o", "./", "指定输出路径")
	//Cmd.Flags().StringArrayVarP(&workloads, "workloads", "w", []string{}, "指定源命名空间，可以多个")
	Cmd.Flags().StringArrayVar(&sourceNamespaces, "src.ns", []string{}, "指定源命名空间，可以多个")
	Cmd.Flags().StringArrayVar(&targetNamespaces, "dst.ns", []string{}, "指定目标命名空间，可以多个")
	Cmd.Flags().StringVar(&sourceKubeConfig, "src.kc", "", "指定源集群的kube-config文件")
	Cmd.Flags().StringVar(&targetKubeConfig, "dst.kc", "", "指定目标集群的kube-config文件")
	Cmd.Flags().StringArrayVarP(&excludes, "excludes", "e", []string{}, "指定需要排除的服务 excludes和includes只能二选一  格式 <namespace>:<workload KIND>:<workload Name>")
	Cmd.Flags().StringArrayVarP(&includes, "includes", "i", []string{}, "指定需要包含的服务 excludes和includes只能二选一  格式 <namespace>:<workload KIND>:<workload Name>")
	Cmd.Flags().BoolVar(&sync, "sync", false, "是否同步到本地文件，当开启时，则不会部署到线上，而是同步成本地yaml文件")

	Cmd.Flags().BoolVarP(&skipConfigMap, "skip-configmap", "c", false, "是否跳过configmap，跳过configmap可能会导致workload无法正常启动")
	Cmd.Flags().BoolVarP(&skipPvPvc, "skip-pv-pvc", "p", false, "是否跳过pv-pvc")
	Cmd.Flags().BoolVarP(&skipSecret, "skip-secret", "s", false, "是否跳过secret")
}
